﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Xml.Linq;
using ICSharpCode.SharpZipLib.Zip;

namespace Meridian
{
    public static class Updater
    {
#if DEBUG
        private const string UpdateUrl = "http://mswin.me/meridian/update-dev.xml";
#else
        private const string UpdateUrl = "http://mswin.me/meridian/update.xml";
#endif
        private const string BaseUrl = "http://mswin.me/meridian/";

        private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

        public static string CheckUpdates()
        {
            var client = new WebClient();
            string result;
            try
            {
                result = client.DownloadString(UpdateUrl);
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return null;
            }

            var xml = XElement.Parse(result);
            var fileTag = xml.Element("File");
            if (fileTag == null || fileTag.Attribute("Build") == null)
            {
                logger.Info("Got update.xml, but can't get build number.");
                return null;
            }

            int updateBuild = int.Parse(fileTag.Attribute("Build").Value);
            if (Assembly.GetExecutingAssembly().GetName().Version.Build >= updateBuild)
                return null;

            if (fileTag.Attribute("Path") == null)
            {
                logger.Info("Got update.xml, but can't get update path.");
                return null;
            }

            return fileTag.Attribute("Path").Value;
        }

        public static bool Update(string updateFile)
        {
            var client = new WebClient();
            var file = Path.GetTempFileName();
            var url = updateFile;
            if (!url.StartsWith("http://"))
                url = BaseUrl + url;

            try
            {
                client.DownloadFile(url, file);
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                return false;
            }

            Unpack(App.Root, file);
            return true;
        }

        private static void Unpack(string path, string file)
        {
            using (var fileStreamIn = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                using (var zipInStream = new ZipInputStream(fileStreamIn))
                {
                    while (true)
                    {
                        ZipEntry entry = zipInStream.GetNextEntry();
                        if (entry == null)
                            break;
                        if (!entry.IsDirectory)
                        {
                            if (File.Exists(path + "\\" + entry.Name))
                            {
                                string name = path + "\\" + entry.Name;
                                while (File.Exists(name))
                                {
                                    name += ".old";
                                }
                                File.Move(path + "\\" + entry.Name, name);
                            }

                            using (var fileStreamOut = new FileStream(string.Format(@"{0}\{1}", path, entry.Name), FileMode.Create, FileAccess.Write))
                            {
                                int size;
                                var buffer = new byte[1024];
                                do
                                {
                                    size = zipInStream.Read(buffer, 0, buffer.Length);
                                    fileStreamOut.Write(buffer, 0, size);
                                } while (size > 0);
                                fileStreamOut.Close();
                            }
                        }
                        else
                            if (!Directory.Exists(string.Format(@"{0}\{1}", path, entry.Name)))
                                Directory.CreateDirectory(string.Format(@"{0}\{1}", path, entry.Name));
                    }
                    zipInStream.Close();
                }
                fileStreamIn.Close();
            }
        }
    }
}
